package wiki.hitime.stl.daq.manager;

import wiki.hitime.stl.daq.bean.bo.DataDbConfigBO;
import wiki.hitime.stl.daq.bean.db.DaqDbConfig;
import wiki.hitime.stl.daq.bean.db.DaqDbDetailConfig;
import wiki.hitime.stl.daq.bean.dto.manage.DbTypeConfigDTO;
import wiki.hitime.stl.daq.enums.DbTypeEnum;
import wiki.hitime.stl.daq.mapper.DaqDbConfigMapper;
import wiki.hitime.stl.daq.service.factory.DataAcquisitionFactory;
import wiki.hitime.stl.daq.support.ContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;
import wiki.hitime.stl.daq.util.UserContextUtil;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 数据库类型配置管理类
 *
 * @author zhangdaoping
 * @create 2019-07-17 10:02
 */
@Service
public class DaqDbConfigManager {

    @Resource
    private DaqDbConfigMapper daqDbConfigMapper;

    @Resource
    private DaqDbDetailConfigManager daqDbDetailConfigManager;

    /**
     * 加载数据源配置信息
     *
     * @param dbConfigId 数据源配置编号
     * @return 数据源配置业务类
     */
    public DataDbConfigBO loadDbConfig(Long dbConfigId) {
        Example selectConfigExample = new Example(DaqDbConfig.class, true, true);
        selectConfigExample.createCriteria().andEqualTo("id", dbConfigId).andEqualTo("isDelete", Boolean.FALSE);
        DaqDbConfig daqDbConfig = daqDbConfigMapper.selectOneByExample(selectConfigExample);
        if (daqDbConfig == null) {
            return null;
        }
        List<DaqDbDetailConfig> detailConfigList = daqDbDetailConfigManager.loadDbDetailConfig(dbConfigId);
        Map<String, String> detailConfigMap = new HashMap<>(detailConfigList.size());
        for (DaqDbDetailConfig detailConfig : detailConfigList) {
            detailConfigMap.put(detailConfig.getDetailConfigKey(), detailConfig.getDetailConfigValue());
        }
        return DataDbConfigBO.builder()
                .name(daqDbConfig.getConfigName())
                .dbTypeEnum(DbTypeEnum.valueOf(daqDbConfig.getDbType()))
                .configProperties(detailConfigMap)
                .build();
    }

    /**
     * 加载数据源实现类
     *
     * @param dbTypeEnum 数据源类型枚举
     * @return 数据源实现类
     */
    public DataAcquisitionFactory loadDbService(DbTypeEnum dbTypeEnum) {
        Map<String, DataAcquisitionFactory> objectMap = ContextHolder.getBeanOfType(DataAcquisitionFactory.class);
        for (Map.Entry entry : objectMap.entrySet()) {
            DataAcquisitionFactory factory = (DataAcquisitionFactory) entry.getValue();
            if (factory.getSupportDbType().equals(dbTypeEnum)) {
                return factory;
            }
        }
        return null;
    }

    /**
     * 获取所有可用的数据类型配置
     *
     * @return 数据类型配置DTO
     */
    public List<DbTypeConfigDTO> listDbTypeConfig() {
        Example selectExample = new Example(DaqDbConfig.class, true, true);
        selectExample.createCriteria().andEqualTo("isDelete", Boolean.FALSE);
        List<DaqDbConfig> daqDbConfigList = daqDbConfigMapper.selectByExample(selectExample);
        return daqDbConfigList.stream().map(this::convertCollDTO).collect(Collectors.toList());
    }

    /**
     * 添加数据库类型配置
     *
     * @param dbTypeConfigDTO 数据库类型
     */
    public void addDbTypeConfig(DbTypeConfigDTO dbTypeConfigDTO) {
        daqDbConfigMapper.insert(convertDb(dbTypeConfigDTO));
    }

    private DbTypeConfigDTO convertCollDTO(DaqDbConfig daqDbConfig) {
        DbTypeEnum dbTypeEnum = DbTypeEnum.valueOf(daqDbConfig.getDbType());
        Assert.notNull(dbTypeEnum, "数据类型枚举为空");
        return DbTypeConfigDTO.builder()
                .configId(daqDbConfig.getId())
                .configName(daqDbConfig.getConfigName())
                .dbType(daqDbConfig.getDbType())
                .dbTypeName(dbTypeEnum.getMsg())
                .build();
    }

    private DaqDbConfig convertDb(DbTypeConfigDTO dbTypeConfigDTO) {
        return DaqDbConfig.builder()
                .configName(dbTypeConfigDTO.getConfigName())
                .dbType(dbTypeConfigDTO.getDbType())
                .createdUserId(UserContextUtil.getJobNumber())
                .createdUser(UserContextUtil.getTrueName())
                .modifiedUserId(UserContextUtil.getJobNumber())
                .modifiedUser(UserContextUtil.getTrueName())
                .ctlVersion(1L)
                .isDelete(Boolean.FALSE)
                .build();
    }
}
